home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / language / harvest.cpt / Harvest C / Tcl 6.2 / stat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-13  |  7.9 KB  |  388 lines

  1.  
  2. #ifdef macintosh
  3. #    pragma segment STAT
  4. #endif
  5.  
  6. /*********************************************************************
  7. File        :    stat.c            -    Macintosh implementation of stat()
  8. Author    :    Matthias Neeracher
  9. Started    :    28May91                                Language    :    MPW C
  10.                 28May91    MN    Created
  11.                 28May91    MN    isatty()
  12. Last        :    28May91
  13.  
  14. Copyright (c) 1991, Matthias Neeracher
  15.  
  16. Permission is granted to anyone to use this software for any
  17. purpose on any computer system, and to redistribute it freely,
  18. subject to the following restrictions:
  19.  
  20. 1. The author is not responsible for the consequences of use of
  21.     this software, no matter how awful, even if they arise
  22.     from defects in it.
  23.  
  24. 2. The origin of this software must not be misrepresented, either
  25.     by explicit claim or by omission.
  26.  
  27. 3. Altered versions must be plainly marked as such, and must not
  28.     be misrepresented as being the original software.
  29.  
  30. THIS VERSION ALTERED FOR USE IN HARVEST C - ERIC W SINK
  31.  
  32. *********************************************************************/
  33.  
  34. #include <string.h>
  35. #include "ioctl.h"
  36. #include <errno.h>
  37. #include <stdio.h>
  38. #ifndef THINK_C
  39. #include <Errors.h>
  40. #include <Files.h>
  41. #endif
  42.  
  43. #include "tcl.h"
  44. #include "tclUnix.h"
  45.  
  46. /* As the field names of a CInfoParamBlockRec are spelled inconsistently,
  47.     we have to use manual casts.
  48. */
  49.  
  50. #define FILEINFO(cb)    (*(HFileInfo *) (cb))
  51. #define DIRINFO(cb)    (*(DirInfo *) (cb))
  52.  
  53. #ifdef THINK_C
  54. FILE *
  55. fd2file(int fd)
  56. {
  57.     register FILE *fp;
  58.     
  59.     if ((unsigned) fd < FOPEN_MAX) {
  60.         fp = &__file[fd];
  61.         if (fp->refnum || fp->std)
  62.             return(fp);
  63.     }
  64.     errno = EBADF;
  65.     return(NULL);
  66. }
  67.  
  68. int ioctl(int fd, unsigned int cmd,long *arg)
  69. {
  70.     FILE *f;
  71.     switch (cmd) {
  72.         case FIOREFNUM:
  73.             f = (FILE *) fd2file(fd);
  74.             return f->refnum;
  75.             break;
  76.         case FIOINTERACTIVE:
  77.             return 0; /* HACK */
  78.             break;
  79.     }
  80. }
  81. #endif
  82.  
  83. OSErr    GetCatInfo(char * path, CInfoPBPtr cb)
  84. {
  85.     char    *    nextPath;
  86.     char    *  tryPath;
  87.     OSErr        err;
  88.     Str255    name;
  89.  
  90.     DIRINFO(cb).ioNamePtr    =    name;
  91.     DIRINFO(cb).ioDrDirID    =    0;
  92.     DIRINFO(cb).ioVRefNum    =    0;
  93.     DIRINFO(cb).ioFDirIndex    =    0;
  94.  
  95.     /* handle very long pathnames */
  96.  
  97.     while (strlen(path) > 255)    {
  98.         for (nextPath    =    path; tryPath = strchr(nextPath, ':'); nextPath = tryPath)
  99.             if (tryPath-nextPath > 31)
  100.                 return bdNamErr;
  101.             else if (tryPath-path > 255)
  102.                 break;
  103.  
  104.         if (nextPath == path && !tryPath)
  105.             return bdNamErr;
  106.  
  107.         name[0]    =    nextPath-path;
  108.         strncpy((char *) name+1, path, name[0]);
  109.  
  110.         err = PBGetCatInfo(cb, false);
  111.         if (err != noErr)
  112.             return err;
  113.  
  114.         if (! (DIRINFO(cb).ioFlAttrib & 0x10)) {
  115.             return bdNamErr;
  116.             }
  117.  
  118.         DIRINFO(cb).ioFDirIndex    =    0;
  119.  
  120.         path    =    nextPath+1;
  121.     }
  122.     
  123.     name[0]    =    strlen(path);
  124.     strncpy((char *) name+1, path, name[0]);
  125.  
  126.     err = PBGetCatInfo(cb, false);
  127.     
  128.     return err;
  129. }
  130.  
  131. OSErr    GetFDCatInfo(int fd, CInfoPBPtr cb)
  132. {
  133.     short                fRef;
  134.     OSErr                err;
  135.     FCBPBRec            fcb;
  136.     Str255            fname;
  137.  
  138.     if (ioctl(fd, FIOREFNUM, (long *) &fRef) == -1)
  139.         return fnfErr;
  140.  
  141.     fcb.ioNamePtr    =     fname;
  142.     fcb.ioRefNum    =    fRef;
  143.     fcb.ioFCBIndx    =     0;
  144.     if (err = PBGetFCBInfo(&fcb, false))
  145.         return err;
  146.  
  147.     FILEINFO(cb).ioNamePtr        =    fname;
  148.     FILEINFO(cb).ioDirID        =    fcb.ioFCBParID;
  149.     FILEINFO(cb).ioVRefNum        =    fcb.ioFCBVRefNum;
  150.     FILEINFO(cb).ioFDirIndex    =    0;
  151.  
  152.     return PBGetCatInfo(cb, false);
  153. }
  154.  
  155. OSErr GetVolume(char * path, ParmBlkPtr pb)
  156. {
  157.     char *    volEnd;
  158.     OSErr        err;
  159.     WDPBRec    wd;
  160.     Str255    name;
  161.  
  162.     volEnd    =    strchr(path, ':');
  163.  
  164.     pb->volumeParam.ioNamePtr    =    name;
  165.  
  166.     if (path[0] == ':' || ! volEnd)    {
  167.         err = PBGetVol(pb, false);
  168.         if (err != noErr)
  169.             return err;
  170.         
  171.         wd.ioNamePtr    =    name;
  172.         wd.ioVRefNum    =     pb->volumeParam.ioVRefNum;
  173.         wd.ioWDIndex    =    0;
  174.         err = PBGetWDInfo(&wd, false);
  175.         if (err == noErr)
  176.             pb->volumeParam.ioVRefNum    =    wd.ioWDVRefNum;
  177.             
  178.         pb->volumeParam.ioVolIndex    =    0;
  179.         }
  180.     else {
  181.         pb->volumeParam.ioVolIndex    =    -1;
  182.  
  183.         name[0]    =    (volEnd - path) + 1; /* include ':' */
  184.         strncpy((char *) name+1, path, name[0]);
  185.         }
  186.  
  187.     err = PBGetVInfo(pb, false);
  188.     
  189.     return err;
  190.     }
  191.  
  192. OSErr GetFDVolume(int fd, ParmBlkPtr pb)
  193. {
  194.     OSErr                err;
  195.     short                fRef;
  196.     Str255            name;
  197.     FCBPBRec            fcb;
  198.  
  199.     if (ioctl(fd, FIOREFNUM, (long *) &fRef) == -1)
  200.         return fnfErr;
  201.  
  202.     fcb.ioNamePtr    =     name;
  203.     fcb.ioRefNum    =    fRef;
  204.     fcb.ioFCBIndx    =     0;
  205.     if (err = PBGetFCBInfo(&fcb, false))
  206.         return err;
  207.  
  208.     pb->volumeParam.ioNamePtr    =    name;
  209.     pb->volumeParam.ioVRefNum    =    fcb.ioFCBVRefNum;
  210.     pb->volumeParam.ioVolIndex    =    0;
  211.  
  212.     return PBGetVInfo(pb, false);
  213. }
  214.  
  215. int    mac_do_stat(CInfoPBPtr cb, ParmBlkPtr pb, struct stat * buf)
  216. {
  217.  
  218.     buf->st_dev        =    pb->ioParam.ioVRefNum;
  219.     buf->st_ino        =    FILEINFO(cb).ioDirID;
  220.     buf->st_nlink    =    1;
  221.     buf->st_uid        =    0;
  222.     buf->st_gid        =    0;
  223.     buf->st_rdev    =    0;
  224.     buf->st_atime    =    FILEINFO(cb).ioFlMdDat;
  225.     buf->st_mtime    =    FILEINFO(cb).ioFlMdDat;
  226.     buf->st_ctime    =    FILEINFO(cb).ioFlCrDat;
  227.     buf->st_blksize=    pb->volumeParam.ioVAlBlkSiz;
  228.  
  229.     if (FILEINFO(cb).ioFlAttrib & 0x10)    {
  230.         buf->st_mode    =    S_IFDIR | 0777;
  231.         buf->st_size    =    buf->st_blksize;    /* Not known for directories    */
  232.     } else {
  233.         buf->st_mode    =    S_IFREG | 0666;
  234.  
  235.         if (FILEINFO(cb).ioFlAttrib & 0x01)
  236.             buf->st_mode &=    0222;
  237.  
  238.         if (FILEINFO(cb).ioFlFndrInfo.fdType == 'APPL')
  239.             buf->st_mode |=    0111;
  240.  
  241.         buf->st_size    =    FILEINFO(cb).ioFlLgLen;        /* Resource fork is ignored    */
  242.     }
  243.  
  244.     buf->st_blocks    =    (buf->st_size + buf->st_blksize - 1) / buf->st_blksize;
  245.  
  246.     return 0;
  247. }
  248.  
  249. int    stat(char * path, struct stat * buf)
  250. {
  251.     int                result;
  252.     CInfoPBRec        cb;
  253.     ParamBlockRec    pb;
  254.  
  255.     if (GetCatInfo(path, &cb) || GetVolume(path, &pb)) {
  256.         errno = ENOENT;
  257.  
  258.         return -1;
  259.     } else {
  260.         result = mac_do_stat(&cb, &pb, buf);
  261.         return result;
  262.         }
  263. }
  264.  
  265. int    lstat(char * path, struct stat * buf)
  266. {
  267.     return stat(path, buf);
  268. }
  269.  
  270. int    fstat(int fd, struct stat * buf)
  271. {
  272.     CInfoPBRec        cb;
  273.     ParamBlockRec    pb;
  274.  
  275.     if (!ioctl(fd, FIOINTERACTIVE, NULL))    {    /* MPW window */
  276.         buf->st_dev            =    0;
  277.         buf->st_ino            =    0;
  278.         buf->st_mode        =    S_IFCHR | 0777;
  279.         buf->st_nlink        =    1;
  280.         buf->st_uid            =    0;
  281.         buf->st_gid            =    0;
  282.         buf->st_rdev        =    0;
  283.         buf->st_size        =    1;
  284.         buf->st_atime        =    time(NULL);
  285.         buf->st_mtime        =    time(NULL);
  286.         buf->st_ctime        =    time(NULL);
  287.         buf->st_blksize    =    1;
  288.         buf->st_blocks        =    1;
  289.  
  290.         return 0;
  291.     }
  292.  
  293.     if (GetFDCatInfo(fd, &cb) || GetFDVolume(fd, &pb)) {
  294.         errno = ENOENT;
  295.  
  296.         return -1;
  297.     } else
  298.         return mac_do_stat(&cb, &pb, buf);
  299. }
  300.  
  301. int
  302. access(const char *filename,int mode)
  303. {
  304. CInfoPBRec        cpb;
  305. int                myresult;
  306. char                myname[256], volname[32];
  307. short                vRefNum;
  308.  
  309.     strncpy(myname, filename, 255);
  310.     myname[255] = '\0';
  311.     c2pstr(myname);
  312.     
  313.     GetVol(volname, &vRefNum);
  314.     
  315.     cpb.hFileInfo.ioCompletion = 0;                /* Synchronous */
  316.     cpb.hFileInfo.ioNamePtr = (unsigned char *) myname;
  317.     cpb.hFileInfo.ioVRefNum = vRefNum;            /* Returned here */
  318.     cpb.hFileInfo.ioFDirIndex = 0;                /* Use ioNamePtr */
  319.     cpb.hFileInfo.ioDirID = 0;                        /* same offset as ioFlNum */
  320.     myresult = PBGetCatInfo(&cpb, (Boolean)0);/* Synchronous */
  321.     if (myresult == noErr) {
  322.         if ((cpb.hFileInfo.ioFlAttrib & ioDirMask) != 0) { /* DIR */
  323.             switch (mode) {
  324.                 case R_OK: return 0;
  325.                 case W_OK: return -1;
  326.                 case X_OK: return 0;
  327.                 case F_OK: return 0;
  328.                 }
  329.             }
  330.         else {
  331.             switch (mode) {
  332.                 case R_OK: return 0;
  333.                 case W_OK: return (cpb.hFileInfo.ioFRefNum > 0) ? -1 : 0;
  334.                 case X_OK: return (cpb.hFileInfo.ioFlFndrInfo.fdType == 'APPL') ? 0 : -1;
  335.                 case F_OK: return 0;
  336.                 }
  337.             }
  338.         }
  339.     
  340.     return -1;
  341.     }
  342.  
  343. #ifndef THINK_C
  344. int isatty(int fd)
  345. {
  346.     return !ioctl(fd, FIOINTERACTIVE, NULL);
  347. }
  348. #endif
  349.  
  350. #ifdef test
  351.  
  352. #include <stdio.h>
  353.  
  354. #define DUMP(EXPR, MODE)    printf("%s = %"#MODE"\n", #EXPR, EXPR);
  355.  
  356. int main(int argc, char ** argv)
  357. {
  358.     int             res;
  359.     struct stat    statbuf;
  360.  
  361.     printf("StdIn is %s TTY.\n", isatty(0)?"a":"no");
  362.     printf("StdOut is %s TTY.\n", isatty(1)?"a":"no");
  363.     printf("StdErr is %s TTY.\n\n", isatty(2)?"a":"no");
  364.     
  365.     if (argc == 1)
  366.         res = fstat(0, &statbuf);
  367.     else
  368.         res = stat(argv[1], &statbuf);
  369.  
  370.     if (res)
  371.         printf("Error occurred.\n");
  372.     else {
  373.         DUMP(statbuf.st_dev,d);
  374.         DUMP(statbuf.st_ino,d);
  375.         DUMP(statbuf.st_mode,#o);
  376.         DUMP(statbuf.st_nlink,d);
  377.         DUMP(statbuf.st_uid,d);
  378.         DUMP(statbuf.st_gid,d);
  379.         DUMP(statbuf.st_rdev,d);
  380.         DUMP(statbuf.st_size,d);
  381.         DUMP(statbuf.st_atime,u);
  382.         DUMP(statbuf.st_mtime,u);
  383.         DUMP(statbuf.st_ctime,u);
  384.         DUMP(statbuf.st_blksize,d);
  385.         DUMP(statbuf.st_blocks,d);
  386.     }
  387. }
  388. #endif